Aller au contenu principal

Opérations intermédiaires

filter

En programmation fonctionnelle Java, filter est une opération intermédiaire puissante utilisée avec les flux (streams) pour sélectionner les éléments d'un flux qui répondent à une condition donnée. Voici une explication détaillée :

Fonctionnement de filter

  • Filtrage basé sur un prédicat :
    • filter prend un prédicat (une fonction qui renvoie un booléen) comme argument.
    • Il évalue le prédicat pour chaque élément du flux.
    • Seuls les éléments pour lesquels le prédicat renvoie true sont inclus dans le nouveau flux résultant.
  • Opération intermédiaire :
    • filter est une opération intermédiaire, ce qui signifie qu'elle renvoie un nouveau flux.
    • Vous pouvez chaîner plusieurs opérations de flux, y compris d'autres opérations filter, après filter.
  • Création d'un nouveau flux :
    • filter ne modifie pas le flux d'origine. Il crée un nouveau flux contenant uniquement les éléments filtrés.

Exemples d'utilisation

  1. Filtrer les nombres pairs :

    List<Integer> nombres = List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
    List<Integer> nombresPairs = nombres.stream()
    .filter(n -> n % 2 == 0)
    .collect(Collectors.toList());
    System.out.println(nombresPairs); // Output: [2, 4, 6, 8, 10]
  2. Filtrer les chaînes de caractères commençant par une lettre spécifique :

    List<String> mots = List.of("pomme", "banane", "orange", "kiwi", "poire");
    List<String> motsEnP = mots.stream()
    .filter(mot -> mot.startsWith("p"))
    .collect(Collectors.toList());
    System.out.println(motsEnP); // Output: [pomme, poire]
  3. Filtrer les objets en fonction d'une propriété :

    class Personne {
    String nom;
    int age;

    public Personne(String nom, int age) {
    this.nom = nom;
    this.age = age;
    }

    public String getNom() {
    return nom;
    }

    public int getAge() {
    return age;
    }

    @Override
    public String toString() {
    return "Personne{" +
    "nom='" + nom + '\'' +
    ", age=" + age +
    '}';
    }
    }

    List<Personne> personnes = List.of(
    new Personne("Alice", 25),
    new Personne("Bob", 30),
    new Personne("Charlie", 20)
    );

    List<Personne> personnesMajeures = personnes.stream()
    .filter(personne -> personne.getAge() >= 18)
    .collect(Collectors.toList());
    System.out.println(personnesMajeures);
    // Output: [Personne{nom='Alice', age=25}, Personne{nom='Bob', age=30}, Personne{nom='Charlie', age=20}]

Points importants

  • filter est une opération intermédiaire, ce qui signifie qu'elle peut être chaînée avec d'autres opérations de flux.
  • Le prédicat utilisé avec filter doit être une fonction sans effets secondaires.
  • filter est une opération paresseuse, ce qui signifie qu'elle n'est exécutée que lorsque une opération terminale est appelée.

Quand utiliser filter

  • Lorsque vous devez sélectionner des éléments d'un flux qui répondent à une condition spécifique.
  • Pour nettoyer ou transformer des données dans un flux.
  • Pour créer des sous-ensembles de données à partir d'un flux.

map

En programmation fonctionnelle Java, map est une opération intermédiaire fondamentale utilisée avec les flux (streams) pour transformer les éléments d'un flux en d'autres éléments. Voici une explication détaillée :

  • Transformation des éléments :
    • map prend une fonction (une fonction qui transforme un élément en un autre) comme argument.
    • Il applique la fonction à chaque élément du flux.
    • Il renvoie un nouveau flux contenant les éléments transformés.
  • Opération intermédiaire :
    • map est une opération intermédiaire, ce qui signifie qu'elle renvoie un nouveau flux.
    • Vous pouvez chaîner plusieurs opérations de flux, y compris d'autres opérations map, après map.
  • Création d'un nouveau flux :
    • map ne modifie pas le flux d'origine. Il crée un nouveau flux contenant les éléments transformés.

Exemples d'utilisation

  1. Mettre en majuscules les chaînes de caractères :

    List<String> mots = List.of("pomme", "banane", "orange");
    List<String> motsMajuscules = mots.stream()
    .map(String::toUpperCase)
    .collect(Collectors.toList());
    System.out.println(motsMajuscules); // Output: [POMME, BANANE, ORANGE]
  2. Calculer les carrés des nombres :

    List<Integer> nombres = List.of(1, 2, 3, 4, 5);
    List<Integer> carres = nombres.stream()
    .map(n -> n * n)
    .collect(Collectors.toList());
    System.out.println(carres); // Output: [1, 4, 9, 16, 25]
  3. Extraire une propriété d'objets :

    class Personne {
    String nom;
    int age;

    public Personne(String nom, int age) {
    this.nom = nom;
    this.age = age;
    }

    public String getNom() {
    return nom;
    }

    public int getAge() {
    return age;
    }

    @Override
    public String toString() {
    return "Personne{" +
    "nom='" + nom + '\'' +
    ", age=" + age +
    '}';
    }
    }

    List<Personne> personnes = List.of(
    new Personne("Alice", 25),
    new Personne("Bob", 30),
    new Personne("Charlie", 20)
    );
    List<String> noms = personnes.stream()
    .map(Personne::getNom)
    .collect(Collectors.toList());
    System.out.println(noms); // Output: [Alice, Bob, Charlie]

Points importants

  • map est une opération intermédiaire, ce qui signifie qu'elle peut être chaînée avec d'autres opérations de flux.
  • La fonction utilisée avec map doit être une fonction sans effets secondaires.
  • map est une opération paresseuse, ce qui signifie qu'elle n'est exécutée que lorsque une opération terminale est appelée.

Quand utiliser map

  • Lorsque vous devez transformer les éléments d'un flux en d'autres éléments.
  • Pour extraire une propriété d'objets dans un flux.
  • Pour effectuer des calculs ou des transformations sur les éléments d'un flux.

En résumé, map est une opération intermédiaire essentielle pour le traitement de flux en Java, permettant de transformer efficacement les éléments d'un flux.

En programmation fonctionnelle Java, sorted est une opération intermédiaire utilisée avec les flux (streams) pour trier les éléments d'un flux. Voici une explication détaillée de son fonctionnement et de son utilisation :

sorted

  • Tri des éléments :
    • sorted trie les éléments du flux en fonction de leur ordre naturel (si les éléments implémentent l'interface Comparable) ou en fonction d'un Comparator fourni.
    • L'ordre naturel est l'ordre défini par la méthode compareTo de l'interface Comparable.
    • Un Comparator est un objet qui définit une méthode compare pour comparer deux éléments.
  • Opération intermédiaire :
    • sorted est une opération intermédiaire, ce qui signifie qu'elle renvoie un nouveau flux.
    • Vous pouvez chaîner plusieurs opérations de flux, y compris d'autres opérations sorted, après sorted.
  • Création d'un nouveau flux trié :
    • sorted ne modifie pas le flux d'origine. Il crée un nouveau flux contenant les éléments triés.

Exemples d'utilisation

  1. Tri de chaînes de caractères par ordre alphabétique :

    List<String> mots = List.of("pomme", "banane", "orange", "kiwi");
    List<String> motsTries = mots.stream().sorted().collect(Collectors.toList());
    System.out.println(motsTries); // Output: [banane, kiwi, orange, pomme]
  2. Tri de nombres par ordre croissant :

    List<Integer> nombres = List.of(5, 2, 8, 1, 9);
    List<Integer> nombresTries = nombres.stream().sorted().collect(Collectors.toList());
    System.out.println(nombresTries); // Output: [1, 2, 5, 8, 9]
  3. Tri d'objets en fonction d'une propriété à l'aide d'un Comparator :

    class Personne {
    String nom;
    int age;

    public Personne(String nom, int age) {
    this.nom = nom;
    this.age = age;
    }

    public String getNom() {
    return nom;
    }

    public int getAge() {
    return age;
    }

    @Override
    public String toString() {
    return "Personne{" + "nom='" + nom + '\'' + ", age=" + age + '}';
    }
    }

    List<Personne> personnes = List.of(
    new Personne("Alice", 25), new Personne("Bob", 30), new Personne("Charlie", 20));
    List<Personne> personnesTrieesParAge = personnes.stream()
    .sorted(Comparator.comparingInt(Personne::getAge)).collect(Collectors.toList());
    System.out.println(personnesTrieesParAge);
    // Output: [Personne{nom='Charlie', age=20}, Personne{nom='Alice', age=25}, Personne{nom='Bob', age=30}]

Points importants

  • sorted est une opération intermédiaire, ce qui signifie qu'elle peut être chaînée avec d'autres opérations de flux.
  • Si vous ne fournissez pas de Comparator, les éléments doivent implémenter l'interface Comparable.
  • sorted est une opération paresseuse, ce qui signifie qu'elle n'est exécutée que lorsqu'une opération terminale est appelée.
  • Lors de l'utilisation de flux parallélisés, le coût de tri peut augmenter, car il faudra combiner les résultats des différents threads.

Quand utiliser sorted

  • Lorsque vous devez trier les éléments d'un flux.
  • Pour présenter les données d'un flux dans un ordre spécifique.
  • Pour faciliter la recherche ou le traitement des données dans un flux.

En programmation fonctionnelle Java, distinct est une opération intermédiaire utilisée avec les flux (streams) pour éliminer les éléments en double d'un flux. Voici une explication détaillée de son fonctionnement et de son utilisation :

distinct

  • Suppression des doublons :
    • distinct compare les éléments du flux en utilisant la méthode equals() de chaque élément.
    • Il crée un nouveau flux qui contient uniquement les éléments uniques, en supprimant les doublons.
  • Opération intermédiaire :
    • distinct est une opération intermédiaire, ce qui signifie qu'elle renvoie un nouveau flux.
    • Vous pouvez chaîner plusieurs opérations de flux, y compris d'autres opérations distinct, après distinct.
  • Création d'un nouveau flux sans doublons :
    • distinct ne modifie pas le flux d'origine. Il crée un nouveau flux contenant uniquement les éléments distincts.

Exemples d'utilisation

  1. Suppression des doublons dans une liste de chaînes de caractères :

    List<String> mots = List.of("pomme", "banane", "pomme", "orange", "banane", "kiwi");
    List<String> motsDistincts = mots.stream().distinct().collect(Collectors.toList());
    System.out.println(motsDistincts); // Output: [pomme, banane, orange, kiwi]
  2. Suppression des doublons dans une liste de nombres :

    List<Integer> nombres = List.of(1, 2, 3, 2, 4, 3, 5);
    List<Integer> nombresDistincts = nombres.stream().distinct().collect(Collectors.toList());
    System.out.println(nombresDistincts); // Output: [1, 2, 3, 4, 5]
  3. Suppression des doublons d'objets personnalisés :

    class Personne {
    String nom;
    int age;

    public Personne(String nom, int age) {
    this.nom = nom;
    this.age = age;
    }

    public String getNom() {
    return nom;
    }

    public int getAge() {
    return age;
    }

    @Override
    public String toString() {
    return "Personne{" + "nom='" + nom + '\'' + ", age=" + age + '}';
    }

    @Override
    public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    Personne personne = (Personne) o;
    return age == personne.age && Objects.equals(nom, personne.nom);
    }

    @Override
    public int hashCode() {
    return Objects.hash(nom, age);
    }
    }

    List<Personne> personnes = List.of(
    new Personne("Alice", 25), new Personne("Bob", 30), new Personne("Alice", 25), new Personne("Charlie", 20));
    List<Personne> personnesDistinctes = personnes.stream().distinct().collect(Collectors.toList());
    System.out.println(personnesDistinctes);
    // Output: [Personne{nom='Alice', age=25}, Personne{nom='Bob', age=30}, Personne{nom='Charlie', age=20}]

Points importants

  • distinct utilise la méthode equals() pour déterminer si deux éléments sont identiques. Il est donc important que les objets personnalisés implémentent correctement la méthode equals() (et hashCode()).
  • distinct est une opération intermédiaire, ce qui signifie qu'elle peut être chaînée avec d'autres opérations de flux.
  • distinct est une opération paresseuse, ce qui signifie qu'elle n'est exécutée que lorsqu'une opération terminale est appelée.
  • L'ordre des éléments dans le flux résultant est préservé.

Quand utiliser distinct

  • Lorsque vous devez supprimer les doublons d'un flux.
  • Pour obtenir une liste d'éléments uniques à partir d'un flux.
  • Pour nettoyer des données en supprimant les entrées en double.

En programmation fonctionnelle Java, limit est une opération intermédiaire utilisée avec les flux (streams) pour réduire la taille d'un flux à un nombre maximal d'éléments. Voici une explication détaillée de son fonctionnement et de son utilisation :

limit

  • Limitation de la taille du flux :
    • limit prend un argument long qui représente le nombre maximal d'éléments que le flux résultant doit contenir.
    • Il crée un nouveau flux qui contient au plus les n premiers éléments du flux d'origine, où n est l'argument fourni.
    • Si le flux d'origine contient moins de n éléments, le flux résultant contiendra tous les éléments du flux d'origine.
  • Opération intermédiaire :
    • limit est une opération intermédiaire, ce qui signifie qu'elle renvoie un nouveau flux.
    • Vous pouvez chaîner plusieurs opérations de flux, y compris d'autres opérations limit, après limit.
  • Création d'un nouveau flux limité :
    • limit ne modifie pas le flux d'origine. Il crée un nouveau flux contenant les éléments limités.

Exemples d'utilisation

  1. Obtenir les 5 premiers éléments d'une liste :

    List<Integer> nombres = List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
    List<Integer> cinqPremiers = nombres.stream().limit(5).collect(Collectors.toList());
    System.out.println(cinqPremiers); // Output: [1, 2, 3, 4, 5]
  2. Obtenir les 3 premières chaînes de caractères :

    List<String> mots = List.of("pomme", "banane", "orange", "kiwi", "poire");
    List<String> troisPremiers = mots.stream().limit(3).collect(Collectors.toList());
    System.out.println(troisPremiers); // Output: [pomme, banane, orange]
  3. Utilisation de limit avec sorted pour obtenir les N plus grands éléments :

    List<Integer> nombres = List.of(5, 2, 8, 1, 9);
    List<Integer> troisPlusGrands = nombres.stream().sorted(Comparator.reverseOrder()).limit(3).collect(Collectors.toList());
    System.out.println(troisPlusGrands); // Output: [9, 8, 5]

Points importants

  • limit est une opération intermédiaire, ce qui signifie qu'elle peut être chaînée avec d'autres opérations de flux.
  • limit est une opération paresseuse, ce qui signifie qu'elle n'est exécutée que lorsqu'une opération terminale est appelée.
  • limit est utile pour traiter de grands flux de données en ne traitant qu'une partie des données.

Quand utiliser limit

  • Lorsque vous devez traiter uniquement les premiers éléments d'un flux.
  • Pour paginer les résultats d'une requête.
  • Pour limiter le nombre d'éléments traités dans un flux infini.

En programmation fonctionnelle Java, skip est une opération intermédiaire utilisée avec les flux (streams) pour ignorer un certain nombre d'éléments au début d'un flux. Voici une explication détaillée de son fonctionnement et de son utilisation :

skip

  • Ignorer les éléments :
    • skip prend un argument long qui représente le nombre d'éléments à ignorer au début du flux.
    • Il crée un nouveau flux qui contient tous les éléments du flux d'origine, sauf les n premiers éléments, où n est l'argument fourni.
    • Si le flux d'origine contient moins de n éléments, le flux résultant sera vide.
  • Opération intermédiaire :
    • skip est une opération intermédiaire, ce qui signifie qu'elle renvoie un nouveau flux.
    • Vous pouvez chaîner plusieurs opérations de flux, y compris d'autres opérations skip, après skip.
  • Création d'un nouveau flux :
    • skip ne modifie pas le flux d'origine. Il crée un nouveau flux contenant les éléments restants après avoir ignoré les premiers éléments.

Exemples d'utilisation

  1. Ignorer les 3 premiers éléments d'une liste :

    List<Integer> nombres = List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
    List<Integer> elementsRestants = nombres.stream().skip(3).collect(Collectors.toList());
    System.out.println(elementsRestants); // Output: [4, 5, 6, 7, 8, 9, 10]
  2. Ignorer les 2 premières chaînes de caractères :

    List<String> mots = List.of("pomme", "banane", "orange", "kiwi", "poire");
    List<String> motsRestants = mots.stream().skip(2).collect(Collectors.toList());
    System.out.println(motsRestants); // Output: [orange, kiwi, poire]
  3. Utilisation de skip pour la pagination :

    List<Integer> nombres = List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
    int page = 2; // Page 2 (en commençant à 1)
    int taillePage = 3;
    List<Integer> elementsPage = nombres.stream().skip((page - 1) * taillePage).limit(taillePage).collect(Collectors.toList());
    System.out.println(elementsPage); // Output: [4, 5, 6]

Points importants

  • skip est une opération intermédiaire, ce qui signifie qu'elle peut être chaînée avec d'autres opérations de flux.
  • skip est une opération paresseuse, ce qui signifie qu'elle n'est exécutée que lorsqu'une opération terminale est appelée.
  • skip est utile pour ignorer les éléments au début d'un flux, par exemple pour la pagination.
  • Si la valeur passée à skip est plus grande que la taille du flux, alors un flux vide sera retourné.

Quand utiliser skip

  • Lorsque vous devez ignorer les premiers éléments d'un flux.
  • Pour implémenter la pagination des résultats.
  • Pour ignorer les en-têtes ou autres informations non pertinentes au début d'un flux de données.

Documentation Oracle : filter, map, sorted, distinct, limit, skip (java.util.stream.Stream)